package com.sj.proxy;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class Proxy {

    /**
     * 用来产生新的代理类
     *
     * @param infce   产生哪个接口的动态代理
     * @param handler 要实现什么样的代理，对接口中的方法前后进行什么样的处理，记录时间or...
     * @return
     * @throws Exception
     */
    public static Object newProxyInstance(Class infce, InvocationHandler handler) throws Exception {
        String rt = "\r\n";
        String methodStr = "";

        Method[] methods = infce.getMethods();
        for (Method m : methods) {
            methodStr +=
                    "    public void " + m.getName() + "() {" + rt +
                            "        try {" + rt +
                            "            Method md = " + infce.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt +
                            "            h.invoke(this, md);" + rt +
                            "        } catch (Exception e) {" + rt +
                            "            e.printStackTrace();" + rt +
                            "        }" + rt +
                            "    }" + rt;
        }

        String src = "package com.sj.proxy;" + rt +
                "import java.lang.reflect.Method;" + rt +
                "public class TankTimeProxy implements " + infce.getName() + " {" + rt +
                "    com.sj.proxy.InvocationHandler h;" + rt +
                "    public TankTimeProxy(InvocationHandler h) {" + rt +
                "        this.h = h;" + rt +
                "    }" + rt +
                methodStr +
                "}";

        String fileUrl = System.getProperty("user.dir") + "/src/main/java/com/sj/proxy";
        String fileName = fileUrl + "/TankTimeProxy.java";
        File file = new File(fileName);
        FileWriter fileWriter = new FileWriter(file);
        fileWriter.write(src);
        fileWriter.flush();
        fileWriter.close();

        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager javaFileManager = compiler.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> compilationUnits = javaFileManager.getJavaFileObjects(fileName);
        JavaCompiler.CompilationTask compilationTask = compiler.getTask(null, javaFileManager, null, null, null, compilationUnits);
        compilationTask.call();
        javaFileManager.close();

        URL[] urls = new URL[]{new URL("file:/" + fileUrl)};
        URLClassLoader urlClassLoader = new URLClassLoader(urls);
        Class clazz = urlClassLoader.loadClass("com.sj.proxy.TankTimeProxy");

        Constructor constructor = clazz.getConstructor(InvocationHandler.class);
        Object m = constructor.newInstance(handler);

        return m;
    }
}
